﻿namespace Skymate.Authorization
{
    using System.Linq;
    using System.Reflection;

    using Fasterflect;

    using Skymate.Authorization.Attributes;
    using Skymate.Authorization.Stors;
    using Skymate.Domain.Specifications;
    using Skymate.Engines;
    using Skymate.Utilities;

    public static class FunctionInit
    {
        public static void InitSystemFunction(
            Assembly assembly)
        {
            var serviceTypes = assembly
                .GetTypes()
                .Where(u=>u.Name.EndsWith("Service"));

            foreach (var serviceType in serviceTypes)
            {
                if (!serviceType.IsDefined(typeof(SystemModelAttribute)))
                {
                    continue;
                }

                var modelAttribute = serviceType.GetCustomAttribute<SystemModelAttribute>();

                
                var methods = serviceType.GetMethods();
                foreach (var methodInfo in methods)
                {
                    if (!methodInfo.IsDefined(typeof(FunctionAttribute)))
                    {
                        continue;
                    }
                    var functionAttribute = methodInfo.GetCustomAttribute<FunctionAttribute>();

                    var function=new SystemFunction();
                    function.ID = GuidHelper.GenerateGuid();
                    function.DisplayText = string.Format("{0}.{1}",modelAttribute.ModelName, functionAttribute.FunctionName);
                    function.FunctionCode = string.Format("{0}.{1}", modelAttribute.ModelCode, functionAttribute.FunctionCode);

                    var functionStore = EngineContext.Current.Resolve<ISystemFunctionStore>();
                    var isExist =
                        functionStore.Exists(
                            Specification<SystemFunction>.Eval(u => u.FunctionCode == function.FunctionCode));
                    if (isExist)
                    {
                        var toUpdate = functionStore.Find(
                            Specification<SystemFunction>.Eval(u => u.FunctionCode == function.FunctionCode));
                        toUpdate.FunctionCode = function.FunctionCode;
                        toUpdate.FunctionName = function.FunctionName;
                        toUpdate.DisplayText = function.DisplayText;
                        functionStore.Update(toUpdate);
                    }
                    else
                    {
                        functionStore.Add(function);
                    }
                    functionStore.Context.Commit();
                }

            }

        }
    }
}